package com.example.lenovo.rxjava_lxy;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.Button;
import android.widget.TextView;

import com.example.lenovo.rxjava_lxy.bean.BaseResult;
import com.example.lenovo.rxjava_lxy.bean.User;
import com.example.lenovo.rxjava_lxy.bean.UserParam;
import com.jakewharton.rxbinding2.view.RxView;
import com.orhanobut.logger.Logger;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.ObservableSource;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.functions.Predicate;
import io.reactivex.schedulers.Schedulers;


public class MainActivity extends AppCompatActivity {

    @BindView(R.id.btCreate)
    Button mBtCreate;
    @BindView(R.id.btJust)
    Button mBtJust;
    @BindView(R.id.btFrom)
    Button mBtFrom;
    @BindView(R.id.btMap)
    Button mBtMap;
    @BindView(R.id.btFlatMap)
    Button mBtFlatMap;
    @BindView(R.id.btScheduler)
    Button mBtScheduler;
    @BindView(R.id.tvContext)
    TextView mTvContext;
    @BindView(R.id.btClickRepeatedly)
    Button mBtClickRepeatedly;
    @BindView(R.id.btMerge)
    Button mBtMerge;
    @BindView(R.id.btCountdown)
    Button mBtCountdown;
    private ArrayList<String> mAl;
    private String LogStr = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Logger.init(LogStr);
        ButterKnife.bind(this);
        getClickRepeatedly();//防止按钮点击

    }

    @OnClick({R.id.btCreate, R.id.btJust, R.id.btFrom, R.id.btMap, R.id.btFlatMap,
            R.id.btScheduler, R.id.btMerge,R.id.btCountdown})
    public void initListener(Button button) {
        switch (button.getId()) {
            case R.id.btCreate:
                Logger.d("开始创建Create");
                getCreate();

                break;
            case R.id.btJust:
                Logger.d("btJust");
                getJust();

                break;
            case R.id.btFrom:
                Logger.d("btFrom");
                getFrom();

                break;
            case R.id.btMap:
                Logger.d("btMap");
                getMap();

                break;
            case R.id.btFlatMap:
                Logger.d("btFlatMap");
                getFlatMap();

                break;
            case R.id.btScheduler:
                Logger.d("btScheduler");
                getScheduler();
                break;
            case R.id.btMerge:
                getMerge();
                break;
            case R.id.btCountdown:
                getCountdown();
                break;
        }
    }

    private void getCountdown() {
    }

    // 假设本地和网络数据合并
    private void getMerge() {
        String username = "";
        Observable.merge(getLocalData(), getNetworkData()).flatMap(new Function<List<User>, ObservableSource<User>>() {
            @Override
            public ObservableSource<User> apply(@NonNull List<User> users) throws Exception {
                return Observable.fromIterable(users);
            }
        }).subscribe(new Consumer<User>() {
            @Override
            public void accept(User user) throws Exception {
                Logger.d(user.getName());
            }
        });


    }

    private Observable<List<User>> getLocalData() {

        List<User> list = new ArrayList<>();
        list.add(new User("1", "name1", "age1"));
        list.add(new User("2", "name2", "age2"));
        return Observable.just(list);
    }

    private Observable<List<User>> getNetworkData() {

        List<User> list = new ArrayList<>();
        list.add(new User("3", "name3", "age3"));
        list.add(new User("4", "name4", "age4"));
        return Observable.just(list);
    }


    // 防止按钮点击
    private void getClickRepeatedly() {
        RxView.clicks(mBtClickRepeatedly).throttleFirst(1, TimeUnit.SECONDS).subscribe(new Consumer<Object>() {
            @Override
            public void accept(Object o) throws Exception {
                Logger.d("我点击了。");
            }
        });

    }


    // 线程切换
    private void getScheduler() {

        Observable.just(1).filter(new Predicate<Integer>() {
            @Override
            public boolean test(@NonNull Integer integer) throws Exception {
                Logger.e("Thread0:" + Thread.currentThread().getName());
                return true;
            }
        }).observeOn(Schedulers.io()).map(new Function<Integer, String>() {
            @Override
            public String apply(@NonNull Integer integer) throws Exception {
                Logger.e("Thread1:" + Thread.currentThread().getName());
                return 1 + "2";
            }
        }).flatMap(new Function<String, ObservableSource<String>>() {
            @Override
            public ObservableSource<String> apply(@NonNull String s) throws Exception {
                Logger.e("Thread2:" + Thread.currentThread().getName());
                return Observable.just(s + 3);
            }
        }).observeOn(AndroidSchedulers.mainThread()).filter(new Predicate<String>() {
            @Override
            public boolean test(@NonNull String s) throws Exception {
                Logger.e("Thread3:" + Thread.currentThread().getName());
                return true;
            }
        }).observeOn(Schedulers.io()).map(new Function<String, String>() {
            @Override
            public String apply(@NonNull String s) throws Exception {
                Logger.e("Thread4:" + Thread.currentThread().getName());
                return s + 4;
            }
        }).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<String>() {
            @Override
            public void accept(String s) throws Exception {
                Logger.e("Thread5:" + Thread.currentThread().getName());
                mTvContext.setText(s);
            }
        });


    }

    //FlatMap+线程
    private void getFlatMap() {
        Observable.just(getUserParam()).subscribeOn(AndroidSchedulers.mainThread())
                .filter(new Predicate<UserParam>() {
                    @Override
                    public boolean test(@NonNull UserParam userParam) throws Exception {
                        Logger.e("Thread0:" + Thread.currentThread().getName());

                        return true;
                    }
                }).observeOn(Schedulers.io()).flatMap(new Function<UserParam, ObservableSource<BaseResult>>() {
            @Override
            public ObservableSource<BaseResult> apply(@NonNull UserParam userParam) throws Exception {
                Logger.e("Thread1:" + Thread.currentThread().getName());
                String userId = userParam.getUserId();
                BaseResult br = new BaseResult("typeli", "successli", "newsli", new User(userId, "name", "age"));

                return Observable.just(br);
            }
        }).flatMap(new Function<BaseResult, ObservableSource<User>>() {
            @Override
            public ObservableSource<User> apply(@NonNull BaseResult baseResult) throws Exception {
                Logger.e("Thread2:" + Thread.currentThread().getName());
                return Observable.just(baseResult.getUser());
            }
        }).observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<User>() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {

                    }

                    @Override
                    public void onNext(@NonNull User user) {
                        Logger.e("Thread3:" + Thread.currentThread().getName());
                        mTvContext.setText(user.toString());
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });


    }

    private void getMap() {
        Observable.just(1).map(new Function<Integer, String>() {
            @Override
            public String apply(@NonNull Integer integer) throws Exception {
                return integer + "haha";
            }
        }).subscribe(new Consumer<String>() {
            @Override
            public void accept(String s) throws Exception {
                mTvContext.setText(s);
            }
        });


    }

    private void getFrom() {
        final StringBuilder str = new StringBuilder();
        // 业务需求：在Integer数组里取出大于2的数据,并在后面添加String字符,显示在页面上。
        Integer[] mInteger = new Integer[5];
        mInteger[0] = 1;
        mInteger[1] = 2;
        mInteger[2] = 3;
        mInteger[3] = 4;
        mInteger[4] = 5;
        Observable.fromArray(mInteger).filter(new Predicate<Integer>() {
            @Override
            public boolean test(@NonNull Integer integer) throws Exception {
                return integer > 2;
            }
        }).map(new Function<Integer, String>() {
            @Override
            public String apply(@NonNull Integer integer) throws Exception {
                return integer + "string";
            }
        }).subscribe(new Consumer<String>() {
            @Override
            public void accept(String s) throws Exception {
                str.append(s);
                mTvContext.setText(str.toString());
            }
        });


    }


    private void getJust() {

        Observable.just("Just第一次调用", "Just第二次调用", "Just第三次调用")
                .subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {

                    }

                    @Override
                    public void onNext(@NonNull String s) {
                        Logger.d(s);
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });


    }

    /**
     * 方法是 RxJava 最基本的创造事件序列的方法。基于这个方法.
     */
    private void getCreate() {

        Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(@NonNull ObservableEmitter<String> e) throws Exception {
                e.onNext("第一次调用");
                e.onNext("第二次调用");
                e.onNext("第三次调用");
            }
        }).subscribe(new Observer<String>() {
            @Override
            public void onSubscribe(@NonNull Disposable d) {

            }

            @Override
            public void onNext(@NonNull String s) {
                Logger.d(s);
            }

            @Override
            public void onError(@NonNull Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        });

    }

    public UserParam getUserParam() {
        UserParam up = new UserParam();
        up.setUserId("123");
        return up;
    }


}
